-- Copyright (c) 2016 John Schember <john@nachtimwald.com>
--
-- Permission is hereby granted, free of charge, to any person obtaining
-- a copy of this software and associated documentation files (the "Software"),
-- to deal in the Software without restriction, including without limitation
-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
-- and/or sell copies of the Software, and to permit persons to whom the
-- Software is furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-- DEALINGS IN THE SOFTWARE.

local string = require("string")
local u64 = require("nums.uintb").u64
local u256 = require("nums.uintb").u256
local u8 = require("nums.uintn").u8

local M = {}
local M_mt = { __metatable = {}, __index = M }

M.digest_size = 64
M.block_size = 64

local C0 = {
    u64("0x18186018C07830D8"), u64("0x23238C2305AF4626"), u64("0xC6C63FC67EF991B8"), u64("0xE8E887E8136FCDFB"),
    u64("0x878726874CA113CB"), u64("0xB8B8DAB8A9626D11"), u64("0x0101040108050209"), u64("0x4F4F214F426E9E0D"),
    u64("0x3636D836ADEE6C9B"), u64("0xA6A6A2A6590451FF"), u64("0xD2D26FD2DEBDB90C"), u64("0xF5F5F3F5FB06F70E"),
    u64("0x7979F979EF80F296"), u64("0x6F6FA16F5FCEDE30"), u64("0x91917E91FCEF3F6D"), u64("0x52525552AA07A4F8"),
    u64("0x60609D6027FDC047"), u64("0xBCBCCABC89766535"), u64("0x9B9B569BACCD2B37"), u64("0x8E8E028E048C018A"),
    u64("0xA3A3B6A371155BD2"), u64("0x0C0C300C603C186C"), u64("0x7B7BF17BFF8AF684"), u64("0x3535D435B5E16A80"),
    u64("0x1D1D741DE8693AF5"), u64("0xE0E0A7E05347DDB3"), u64("0xD7D77BD7F6ACB321"), u64("0xC2C22FC25EED999C"),
    u64("0x2E2EB82E6D965C43"), u64("0x4B4B314B627A9629"), u64("0xFEFEDFFEA321E15D"), u64("0x575741578216AED5"),
    u64("0x15155415A8412ABD"), u64("0x7777C1779FB6EEE8"), u64("0x3737DC37A5EB6E92"), u64("0xE5E5B3E57B56D79E"),
    u64("0x9F9F469F8CD92313"), u64("0xF0F0E7F0D317FD23"), u64("0x4A4A354A6A7F9420"), u64("0xDADA4FDA9E95A944"),
    u64("0x58587D58FA25B0A2"), u64("0xC9C903C906CA8FCF"), u64("0x2929A429558D527C"), u64("0x0A0A280A5022145A"),
    u64("0xB1B1FEB1E14F7F50"), u64("0xA0A0BAA0691A5DC9"), u64("0x6B6BB16B7FDAD614"), u64("0x85852E855CAB17D9"),
    u64("0xBDBDCEBD8173673C"), u64("0x5D5D695DD234BA8F"), u64("0x1010401080502090"), u64("0xF4F4F7F4F303F507"),
    u64("0xCBCB0BCB16C08BDD"), u64("0x3E3EF83EEDC67CD3"), u64("0x0505140528110A2D"), u64("0x676781671FE6CE78"),
    u64("0xE4E4B7E47353D597"), u64("0x27279C2725BB4E02"), u64("0x4141194132588273"), u64("0x8B8B168B2C9D0BA7"),
    u64("0xA7A7A6A7510153F6"), u64("0x7D7DE97DCF94FAB2"), u64("0x95956E95DCFB3749"), u64("0xD8D847D88E9FAD56"),
    u64("0xFBFBCBFB8B30EB70"), u64("0xEEEE9FEE2371C1CD"), u64("0x7C7CED7CC791F8BB"), u64("0x6666856617E3CC71"),
    u64("0xDDDD53DDA68EA77B"), u64("0x17175C17B84B2EAF"), u64("0x4747014702468E45"), u64("0x9E9E429E84DC211A"),
    u64("0xCACA0FCA1EC589D4"), u64("0x2D2DB42D75995A58"), u64("0xBFBFC6BF9179632E"), u64("0x07071C07381B0E3F"),
    u64("0xADAD8EAD012347AC"), u64("0x5A5A755AEA2FB4B0"), u64("0x838336836CB51BEF"), u64("0x3333CC3385FF66B6"),
    u64("0x636391633FF2C65C"), u64("0x02020802100A0412"), u64("0xAAAA92AA39384993"), u64("0x7171D971AFA8E2DE"),
    u64("0xC8C807C80ECF8DC6"), u64("0x19196419C87D32D1"), u64("0x494939497270923B"), u64("0xD9D943D9869AAF5F"),
    u64("0xF2F2EFF2C31DF931"), u64("0xE3E3ABE34B48DBA8"), u64("0x5B5B715BE22AB6B9"), u64("0x88881A8834920DBC"),
    u64("0x9A9A529AA4C8293E"), u64("0x262698262DBE4C0B"), u64("0x3232C8328DFA64BF"), u64("0xB0B0FAB0E94A7D59"),
    u64("0xE9E983E91B6ACFF2"), u64("0x0F0F3C0F78331E77"), u64("0xD5D573D5E6A6B733"), u64("0x80803A8074BA1DF4"),
    u64("0xBEBEC2BE997C6127"), u64("0xCDCD13CD26DE87EB"), u64("0x3434D034BDE46889"), u64("0x48483D487A759032"),
    u64("0xFFFFDBFFAB24E354"), u64("0x7A7AF57AF78FF48D"), u64("0x90907A90F4EA3D64"), u64("0x5F5F615FC23EBE9D"),
    u64("0x202080201DA0403D"), u64("0x6868BD6867D5D00F"), u64("0x1A1A681AD07234CA"), u64("0xAEAE82AE192C41B7"),
    u64("0xB4B4EAB4C95E757D"), u64("0x54544D549A19A8CE"), u64("0x93937693ECE53B7F"), u64("0x222288220DAA442F"),
    u64("0x64648D6407E9C863"), u64("0xF1F1E3F1DB12FF2A"), u64("0x7373D173BFA2E6CC"), u64("0x12124812905A2482"),
    u64("0x40401D403A5D807A"), u64("0x0808200840281048"), u64("0xC3C32BC356E89B95"), u64("0xECEC97EC337BC5DF"),
    u64("0xDBDB4BDB9690AB4D"), u64("0xA1A1BEA1611F5FC0"), u64("0x8D8D0E8D1C830791"), u64("0x3D3DF43DF5C97AC8"),
    u64("0x97976697CCF1335B"), u64("0x0000000000000000"), u64("0xCFCF1BCF36D483F9"), u64("0x2B2BAC2B4587566E"),
    u64("0x7676C57697B3ECE1"), u64("0x8282328264B019E6"), u64("0xD6D67FD6FEA9B128"), u64("0x1B1B6C1BD87736C3"),
    u64("0xB5B5EEB5C15B7774"), u64("0xAFAF86AF112943BE"), u64("0x6A6AB56A77DFD41D"), u64("0x50505D50BA0DA0EA"),
    u64("0x45450945124C8A57"), u64("0xF3F3EBF3CB18FB38"), u64("0x3030C0309DF060AD"), u64("0xEFEF9BEF2B74C3C4"),
    u64("0x3F3FFC3FE5C37EDA"), u64("0x55554955921CAAC7"), u64("0xA2A2B2A2791059DB"), u64("0xEAEA8FEA0365C9E9"),
    u64("0x656589650FECCA6A"), u64("0xBABAD2BAB9686903"), u64("0x2F2FBC2F65935E4A"), u64("0xC0C027C04EE79D8E"),
    u64("0xDEDE5FDEBE81A160"), u64("0x1C1C701CE06C38FC"), u64("0xFDFDD3FDBB2EE746"), u64("0x4D4D294D52649A1F"),
    u64("0x92927292E4E03976"), u64("0x7575C9758FBCEAFA"), u64("0x06061806301E0C36"), u64("0x8A8A128A249809AE"),
    u64("0xB2B2F2B2F940794B"), u64("0xE6E6BFE66359D185"), u64("0x0E0E380E70361C7E"), u64("0x1F1F7C1FF8633EE7"),
    u64("0x6262956237F7C455"), u64("0xD4D477D4EEA3B53A"), u64("0xA8A89AA829324D81"), u64("0x96966296C4F43152"),
    u64("0xF9F9C3F99B3AEF62"), u64("0xC5C533C566F697A3"), u64("0x2525942535B14A10"), u64("0x59597959F220B2AB"),
    u64("0x84842A8454AE15D0"), u64("0x7272D572B7A7E4C5"), u64("0x3939E439D5DD72EC"), u64("0x4C4C2D4C5A619816"),
    u64("0x5E5E655ECA3BBC94"), u64("0x7878FD78E785F09F"), u64("0x3838E038DDD870E5"), u64("0x8C8C0A8C14860598"),
    u64("0xD1D163D1C6B2BF17"), u64("0xA5A5AEA5410B57E4"), u64("0xE2E2AFE2434DD9A1"), u64("0x616199612FF8C24E"),
    u64("0xB3B3F6B3F1457B42"), u64("0x2121842115A54234"), u64("0x9C9C4A9C94D62508"), u64("0x1E1E781EF0663CEE"),
    u64("0x4343114322528661"), u64("0xC7C73BC776FC93B1"), u64("0xFCFCD7FCB32BE54F"), u64("0x0404100420140824"),
    u64("0x51515951B208A2E3"), u64("0x99995E99BCC72F25"), u64("0x6D6DA96D4FC4DA22"), u64("0x0D0D340D68391A65"),
    u64("0xFAFACFFA8335E979"), u64("0xDFDF5BDFB684A369"), u64("0x7E7EE57ED79BFCA9"), u64("0x242490243DB44819"),
    u64("0x3B3BEC3BC5D776FE"), u64("0xABAB96AB313D4B9A"), u64("0xCECE1FCE3ED181F0"), u64("0x1111441188552299"),
    u64("0x8F8F068F0C890383"), u64("0x4E4E254E4A6B9C04"), u64("0xB7B7E6B7D1517366"), u64("0xEBEB8BEB0B60CBE0"),
    u64("0x3C3CF03CFDCC78C1"), u64("0x81813E817CBF1FFD"), u64("0x94946A94D4FE3540"), u64("0xF7F7FBF7EB0CF31C"),
    u64("0xB9B9DEB9A1676F18"), u64("0x13134C13985F268B"), u64("0x2C2CB02C7D9C5851"), u64("0xD3D36BD3D6B8BB05"),
    u64("0xE7E7BBE76B5CD38C"), u64("0x6E6EA56E57CBDC39"), u64("0xC4C437C46EF395AA"), u64("0x03030C03180F061B"),
    u64("0x565645568A13ACDC"), u64("0x44440D441A49885E"), u64("0x7F7FE17FDF9EFEA0"), u64("0xA9A99EA921374F88"),
    u64("0x2A2AA82A4D825467"), u64("0xBBBBD6BBB16D6B0A"), u64("0xC1C123C146E29F87"), u64("0x53535153A202A6F1"),
    u64("0xDCDC57DCAE8BA572"), u64("0x0B0B2C0B58271653"), u64("0x9D9D4E9D9CD32701"), u64("0x6C6CAD6C47C1D82B"),
    u64("0x3131C43195F562A4"), u64("0x7474CD7487B9E8F3"), u64("0xF6F6FFF6E309F115"), u64("0x464605460A438C4C"),
    u64("0xACAC8AAC092645A5"), u64("0x89891E893C970FB5"), u64("0x14145014A04428B4"), u64("0xE1E1A3E15B42DFBA"),
    u64("0x16165816B04E2CA6"), u64("0x3A3AE83ACDD274F7"), u64("0x6969B9696FD0D206"), u64("0x09092409482D1241"),
    u64("0x7070DD70A7ADE0D7"), u64("0xB6B6E2B6D954716F"), u64("0xD0D067D0CEB7BD1E"), u64("0xEDED93ED3B7EC7D6"),
    u64("0xCCCC17CC2EDB85E2"), u64("0x424215422A578468"), u64("0x98985A98B4C22D2C"), u64("0xA4A4AAA4490E55ED"),
    u64("0x2828A0285D885075"), u64("0x5C5C6D5CDA31B886"), u64("0xF8F8C7F8933FED6B"), u64("0x8686228644A411C2")
}

local C1 = {
    u64("0xD818186018C07830"), u64("0x2623238C2305AF46"), u64("0xB8C6C63FC67EF991"), u64("0xFBE8E887E8136FCD"),
    u64("0xCB878726874CA113"), u64("0x11B8B8DAB8A9626D"), u64("0x0901010401080502"), u64("0x0D4F4F214F426E9E"),
    u64("0x9B3636D836ADEE6C"), u64("0xFFA6A6A2A6590451"), u64("0x0CD2D26FD2DEBDB9"), u64("0x0EF5F5F3F5FB06F7"),
    u64("0x967979F979EF80F2"), u64("0x306F6FA16F5FCEDE"), u64("0x6D91917E91FCEF3F"), u64("0xF852525552AA07A4"),
    u64("0x4760609D6027FDC0"), u64("0x35BCBCCABC897665"), u64("0x379B9B569BACCD2B"), u64("0x8A8E8E028E048C01"),
    u64("0xD2A3A3B6A371155B"), u64("0x6C0C0C300C603C18"), u64("0x847B7BF17BFF8AF6"), u64("0x803535D435B5E16A"),
    u64("0xF51D1D741DE8693A"), u64("0xB3E0E0A7E05347DD"), u64("0x21D7D77BD7F6ACB3"), u64("0x9CC2C22FC25EED99"),
    u64("0x432E2EB82E6D965C"), u64("0x294B4B314B627A96"), u64("0x5DFEFEDFFEA321E1"), u64("0xD5575741578216AE"),
    u64("0xBD15155415A8412A"), u64("0xE87777C1779FB6EE"), u64("0x923737DC37A5EB6E"), u64("0x9EE5E5B3E57B56D7"),
    u64("0x139F9F469F8CD923"), u64("0x23F0F0E7F0D317FD"), u64("0x204A4A354A6A7F94"), u64("0x44DADA4FDA9E95A9"),
    u64("0xA258587D58FA25B0"), u64("0xCFC9C903C906CA8F"), u64("0x7C2929A429558D52"), u64("0x5A0A0A280A502214"),
    u64("0x50B1B1FEB1E14F7F"), u64("0xC9A0A0BAA0691A5D"), u64("0x146B6BB16B7FDAD6"), u64("0xD985852E855CAB17"),
    u64("0x3CBDBDCEBD817367"), u64("0x8F5D5D695DD234BA"), u64("0x9010104010805020"), u64("0x07F4F4F7F4F303F5"),
    u64("0xDDCBCB0BCB16C08B"), u64("0xD33E3EF83EEDC67C"), u64("0x2D0505140528110A"), u64("0x78676781671FE6CE"),
    u64("0x97E4E4B7E47353D5"), u64("0x0227279C2725BB4E"), u64("0x7341411941325882"), u64("0xA78B8B168B2C9D0B"),
    u64("0xF6A7A7A6A7510153"), u64("0xB27D7DE97DCF94FA"), u64("0x4995956E95DCFB37"), u64("0x56D8D847D88E9FAD"),
    u64("0x70FBFBCBFB8B30EB"), u64("0xCDEEEE9FEE2371C1"), u64("0xBB7C7CED7CC791F8"), u64("0x716666856617E3CC"),
    u64("0x7BDDDD53DDA68EA7"), u64("0xAF17175C17B84B2E"), u64("0x454747014702468E"), u64("0x1A9E9E429E84DC21"),
    u64("0xD4CACA0FCA1EC589"), u64("0x582D2DB42D75995A"), u64("0x2EBFBFC6BF917963"), u64("0x3F07071C07381B0E"),
    u64("0xACADAD8EAD012347"), u64("0xB05A5A755AEA2FB4"), u64("0xEF838336836CB51B"), u64("0xB63333CC3385FF66"),
    u64("0x5C636391633FF2C6"), u64("0x1202020802100A04"), u64("0x93AAAA92AA393849"), u64("0xDE7171D971AFA8E2"),
    u64("0xC6C8C807C80ECF8D"), u64("0xD119196419C87D32"), u64("0x3B49493949727092"), u64("0x5FD9D943D9869AAF"),
    u64("0x31F2F2EFF2C31DF9"), u64("0xA8E3E3ABE34B48DB"), u64("0xB95B5B715BE22AB6"), u64("0xBC88881A8834920D"),
    u64("0x3E9A9A529AA4C829"), u64("0x0B262698262DBE4C"), u64("0xBF3232C8328DFA64"), u64("0x59B0B0FAB0E94A7D"),
    u64("0xF2E9E983E91B6ACF"), u64("0x770F0F3C0F78331E"), u64("0x33D5D573D5E6A6B7"), u64("0xF480803A8074BA1D"),
    u64("0x27BEBEC2BE997C61"), u64("0xEBCDCD13CD26DE87"), u64("0x893434D034BDE468"), u64("0x3248483D487A7590"),
    u64("0x54FFFFDBFFAB24E3"), u64("0x8D7A7AF57AF78FF4"), u64("0x6490907A90F4EA3D"), u64("0x9D5F5F615FC23EBE"),
    u64("0x3D202080201DA040"), u64("0x0F6868BD6867D5D0"), u64("0xCA1A1A681AD07234"), u64("0xB7AEAE82AE192C41"),
    u64("0x7DB4B4EAB4C95E75"), u64("0xCE54544D549A19A8"), u64("0x7F93937693ECE53B"), u64("0x2F222288220DAA44"),
    u64("0x6364648D6407E9C8"), u64("0x2AF1F1E3F1DB12FF"), u64("0xCC7373D173BFA2E6"), u64("0x8212124812905A24"),
    u64("0x7A40401D403A5D80"), u64("0x4808082008402810"), u64("0x95C3C32BC356E89B"), u64("0xDFECEC97EC337BC5"),
    u64("0x4DDBDB4BDB9690AB"), u64("0xC0A1A1BEA1611F5F"), u64("0x918D8D0E8D1C8307"), u64("0xC83D3DF43DF5C97A"),
    u64("0x5B97976697CCF133"), u64("0x0000000000000000"), u64("0xF9CFCF1BCF36D483"), u64("0x6E2B2BAC2B458756"),
    u64("0xE17676C57697B3EC"), u64("0xE68282328264B019"), u64("0x28D6D67FD6FEA9B1"), u64("0xC31B1B6C1BD87736"),
    u64("0x74B5B5EEB5C15B77"), u64("0xBEAFAF86AF112943"), u64("0x1D6A6AB56A77DFD4"), u64("0xEA50505D50BA0DA0"),
    u64("0x5745450945124C8A"), u64("0x38F3F3EBF3CB18FB"), u64("0xAD3030C0309DF060"), u64("0xC4EFEF9BEF2B74C3"),
    u64("0xDA3F3FFC3FE5C37E"), u64("0xC755554955921CAA"), u64("0xDBA2A2B2A2791059"), u64("0xE9EAEA8FEA0365C9"),
    u64("0x6A656589650FECCA"), u64("0x03BABAD2BAB96869"), u64("0x4A2F2FBC2F65935E"), u64("0x8EC0C027C04EE79D"),
    u64("0x60DEDE5FDEBE81A1"), u64("0xFC1C1C701CE06C38"), u64("0x46FDFDD3FDBB2EE7"), u64("0x1F4D4D294D52649A"),
    u64("0x7692927292E4E039"), u64("0xFA7575C9758FBCEA"), u64("0x3606061806301E0C"), u64("0xAE8A8A128A249809"),
    u64("0x4BB2B2F2B2F94079"), u64("0x85E6E6BFE66359D1"), u64("0x7E0E0E380E70361C"), u64("0xE71F1F7C1FF8633E"),
    u64("0x556262956237F7C4"), u64("0x3AD4D477D4EEA3B5"), u64("0x81A8A89AA829324D"), u64("0x5296966296C4F431"),
    u64("0x62F9F9C3F99B3AEF"), u64("0xA3C5C533C566F697"), u64("0x102525942535B14A"), u64("0xAB59597959F220B2"),
    u64("0xD084842A8454AE15"), u64("0xC57272D572B7A7E4"), u64("0xEC3939E439D5DD72"), u64("0x164C4C2D4C5A6198"),
    u64("0x945E5E655ECA3BBC"), u64("0x9F7878FD78E785F0"), u64("0xE53838E038DDD870"), u64("0x988C8C0A8C148605"),
    u64("0x17D1D163D1C6B2BF"), u64("0xE4A5A5AEA5410B57"), u64("0xA1E2E2AFE2434DD9"), u64("0x4E616199612FF8C2"),
    u64("0x42B3B3F6B3F1457B"), u64("0x342121842115A542"), u64("0x089C9C4A9C94D625"), u64("0xEE1E1E781EF0663C"),
    u64("0x6143431143225286"), u64("0xB1C7C73BC776FC93"), u64("0x4FFCFCD7FCB32BE5"), u64("0x2404041004201408"),
    u64("0xE351515951B208A2"), u64("0x2599995E99BCC72F"), u64("0x226D6DA96D4FC4DA"), u64("0x650D0D340D68391A"),
    u64("0x79FAFACFFA8335E9"), u64("0x69DFDF5BDFB684A3"), u64("0xA97E7EE57ED79BFC"), u64("0x19242490243DB448"),
    u64("0xFE3B3BEC3BC5D776"), u64("0x9AABAB96AB313D4B"), u64("0xF0CECE1FCE3ED181"), u64("0x9911114411885522"),
    u64("0x838F8F068F0C8903"), u64("0x044E4E254E4A6B9C"), u64("0x66B7B7E6B7D15173"), u64("0xE0EBEB8BEB0B60CB"),
    u64("0xC13C3CF03CFDCC78"), u64("0xFD81813E817CBF1F"), u64("0x4094946A94D4FE35"), u64("0x1CF7F7FBF7EB0CF3"),
    u64("0x18B9B9DEB9A1676F"), u64("0x8B13134C13985F26"), u64("0x512C2CB02C7D9C58"), u64("0x05D3D36BD3D6B8BB"),
    u64("0x8CE7E7BBE76B5CD3"), u64("0x396E6EA56E57CBDC"), u64("0xAAC4C437C46EF395"), u64("0x1B03030C03180F06"),
    u64("0xDC565645568A13AC"), u64("0x5E44440D441A4988"), u64("0xA07F7FE17FDF9EFE"), u64("0x88A9A99EA921374F"),
    u64("0x672A2AA82A4D8254"), u64("0x0ABBBBD6BBB16D6B"), u64("0x87C1C123C146E29F"), u64("0xF153535153A202A6"),
    u64("0x72DCDC57DCAE8BA5"), u64("0x530B0B2C0B582716"), u64("0x019D9D4E9D9CD327"), u64("0x2B6C6CAD6C47C1D8"),
    u64("0xA43131C43195F562"), u64("0xF37474CD7487B9E8"), u64("0x15F6F6FFF6E309F1"), u64("0x4C464605460A438C"),
    u64("0xA5ACAC8AAC092645"), u64("0xB589891E893C970F"), u64("0xB414145014A04428"), u64("0xBAE1E1A3E15B42DF"),
    u64("0xA616165816B04E2C"), u64("0xF73A3AE83ACDD274"), u64("0x066969B9696FD0D2"), u64("0x4109092409482D12"),
    u64("0xD77070DD70A7ADE0"), u64("0x6FB6B6E2B6D95471"), u64("0x1ED0D067D0CEB7BD"), u64("0xD6EDED93ED3B7EC7"),
    u64("0xE2CCCC17CC2EDB85"), u64("0x68424215422A5784"), u64("0x2C98985A98B4C22D"), u64("0xEDA4A4AAA4490E55"),
    u64("0x752828A0285D8850"), u64("0x865C5C6D5CDA31B8"), u64("0x6BF8F8C7F8933FED"), u64("0xC28686228644A411")
}

local C2 = {
    u64("0x30D818186018C078"), u64("0x462623238C2305AF"), u64("0x91B8C6C63FC67EF9"), u64("0xCDFBE8E887E8136F"),
    u64("0x13CB878726874CA1"), u64("0x6D11B8B8DAB8A962"), u64("0x0209010104010805"), u64("0x9E0D4F4F214F426E"),
    u64("0x6C9B3636D836ADEE"), u64("0x51FFA6A6A2A65904"), u64("0xB90CD2D26FD2DEBD"), u64("0xF70EF5F5F3F5FB06"),
    u64("0xF2967979F979EF80"), u64("0xDE306F6FA16F5FCE"), u64("0x3F6D91917E91FCEF"), u64("0xA4F852525552AA07"),
    u64("0xC04760609D6027FD"), u64("0x6535BCBCCABC8976"), u64("0x2B379B9B569BACCD"), u64("0x018A8E8E028E048C"),
    u64("0x5BD2A3A3B6A37115"), u64("0x186C0C0C300C603C"), u64("0xF6847B7BF17BFF8A"), u64("0x6A803535D435B5E1"),
    u64("0x3AF51D1D741DE869"), u64("0xDDB3E0E0A7E05347"), u64("0xB321D7D77BD7F6AC"), u64("0x999CC2C22FC25EED"),
    u64("0x5C432E2EB82E6D96"), u64("0x96294B4B314B627A"), u64("0xE15DFEFEDFFEA321"), u64("0xAED5575741578216"),
    u64("0x2ABD15155415A841"), u64("0xEEE87777C1779FB6"), u64("0x6E923737DC37A5EB"), u64("0xD79EE5E5B3E57B56"),
    u64("0x23139F9F469F8CD9"), u64("0xFD23F0F0E7F0D317"), u64("0x94204A4A354A6A7F"), u64("0xA944DADA4FDA9E95"),
    u64("0xB0A258587D58FA25"), u64("0x8FCFC9C903C906CA"), u64("0x527C2929A429558D"), u64("0x145A0A0A280A5022"),
    u64("0x7F50B1B1FEB1E14F"), u64("0x5DC9A0A0BAA0691A"), u64("0xD6146B6BB16B7FDA"), u64("0x17D985852E855CAB"),
    u64("0x673CBDBDCEBD8173"), u64("0xBA8F5D5D695DD234"), u64("0x2090101040108050"), u64("0xF507F4F4F7F4F303"),
    u64("0x8BDDCBCB0BCB16C0"), u64("0x7CD33E3EF83EEDC6"), u64("0x0A2D050514052811"), u64("0xCE78676781671FE6"),
    u64("0xD597E4E4B7E47353"), u64("0x4E0227279C2725BB"), u64("0x8273414119413258"), u64("0x0BA78B8B168B2C9D"),
    u64("0x53F6A7A7A6A75101"), u64("0xFAB27D7DE97DCF94"), u64("0x374995956E95DCFB"), u64("0xAD56D8D847D88E9F"),
    u64("0xEB70FBFBCBFB8B30"), u64("0xC1CDEEEE9FEE2371"), u64("0xF8BB7C7CED7CC791"), u64("0xCC716666856617E3"),
    u64("0xA77BDDDD53DDA68E"), u64("0x2EAF17175C17B84B"), u64("0x8E45474701470246"), u64("0x211A9E9E429E84DC"),
    u64("0x89D4CACA0FCA1EC5"), u64("0x5A582D2DB42D7599"), u64("0x632EBFBFC6BF9179"), u64("0x0E3F07071C07381B"),
    u64("0x47ACADAD8EAD0123"), u64("0xB4B05A5A755AEA2F"), u64("0x1BEF838336836CB5"), u64("0x66B63333CC3385FF"),
    u64("0xC65C636391633FF2"), u64("0x041202020802100A"), u64("0x4993AAAA92AA3938"), u64("0xE2DE7171D971AFA8"),
    u64("0x8DC6C8C807C80ECF"), u64("0x32D119196419C87D"), u64("0x923B494939497270"), u64("0xAF5FD9D943D9869A"),
    u64("0xF931F2F2EFF2C31D"), u64("0xDBA8E3E3ABE34B48"), u64("0xB6B95B5B715BE22A"), u64("0x0DBC88881A883492"),
    u64("0x293E9A9A529AA4C8"), u64("0x4C0B262698262DBE"), u64("0x64BF3232C8328DFA"), u64("0x7D59B0B0FAB0E94A"),
    u64("0xCFF2E9E983E91B6A"), u64("0x1E770F0F3C0F7833"), u64("0xB733D5D573D5E6A6"), u64("0x1DF480803A8074BA"),
    u64("0x6127BEBEC2BE997C"), u64("0x87EBCDCD13CD26DE"), u64("0x68893434D034BDE4"), u64("0x903248483D487A75"),
    u64("0xE354FFFFDBFFAB24"), u64("0xF48D7A7AF57AF78F"), u64("0x3D6490907A90F4EA"), u64("0xBE9D5F5F615FC23E"),
    u64("0x403D202080201DA0"), u64("0xD00F6868BD6867D5"), u64("0x34CA1A1A681AD072"), u64("0x41B7AEAE82AE192C"),
    u64("0x757DB4B4EAB4C95E"), u64("0xA8CE54544D549A19"), u64("0x3B7F93937693ECE5"), u64("0x442F222288220DAA"),
    u64("0xC86364648D6407E9"), u64("0xFF2AF1F1E3F1DB12"), u64("0xE6CC7373D173BFA2"), u64("0x248212124812905A"),
    u64("0x807A40401D403A5D"), u64("0x1048080820084028"), u64("0x9B95C3C32BC356E8"), u64("0xC5DFECEC97EC337B"),
    u64("0xAB4DDBDB4BDB9690"), u64("0x5FC0A1A1BEA1611F"), u64("0x07918D8D0E8D1C83"), u64("0x7AC83D3DF43DF5C9"),
    u64("0x335B97976697CCF1"), u64("0x0000000000000000"), u64("0x83F9CFCF1BCF36D4"), u64("0x566E2B2BAC2B4587"),
    u64("0xECE17676C57697B3"), u64("0x19E68282328264B0"), u64("0xB128D6D67FD6FEA9"), u64("0x36C31B1B6C1BD877"),
    u64("0x7774B5B5EEB5C15B"), u64("0x43BEAFAF86AF1129"), u64("0xD41D6A6AB56A77DF"), u64("0xA0EA50505D50BA0D"),
    u64("0x8A5745450945124C"), u64("0xFB38F3F3EBF3CB18"), u64("0x60AD3030C0309DF0"), u64("0xC3C4EFEF9BEF2B74"),
    u64("0x7EDA3F3FFC3FE5C3"), u64("0xAAC755554955921C"), u64("0x59DBA2A2B2A27910"), u64("0xC9E9EAEA8FEA0365"),
    u64("0xCA6A656589650FEC"), u64("0x6903BABAD2BAB968"), u64("0x5E4A2F2FBC2F6593"), u64("0x9D8EC0C027C04EE7"),
    u64("0xA160DEDE5FDEBE81"), u64("0x38FC1C1C701CE06C"), u64("0xE746FDFDD3FDBB2E"), u64("0x9A1F4D4D294D5264"),
    u64("0x397692927292E4E0"), u64("0xEAFA7575C9758FBC"), u64("0x0C3606061806301E"), u64("0x09AE8A8A128A2498"),
    u64("0x794BB2B2F2B2F940"), u64("0xD185E6E6BFE66359"), u64("0x1C7E0E0E380E7036"), u64("0x3EE71F1F7C1FF863"),
    u64("0xC4556262956237F7"), u64("0xB53AD4D477D4EEA3"), u64("0x4D81A8A89AA82932"), u64("0x315296966296C4F4"),
    u64("0xEF62F9F9C3F99B3A"), u64("0x97A3C5C533C566F6"), u64("0x4A102525942535B1"), u64("0xB2AB59597959F220"),
    u64("0x15D084842A8454AE"), u64("0xE4C57272D572B7A7"), u64("0x72EC3939E439D5DD"), u64("0x98164C4C2D4C5A61"),
    u64("0xBC945E5E655ECA3B"), u64("0xF09F7878FD78E785"), u64("0x70E53838E038DDD8"), u64("0x05988C8C0A8C1486"),
    u64("0xBF17D1D163D1C6B2"), u64("0x57E4A5A5AEA5410B"), u64("0xD9A1E2E2AFE2434D"), u64("0xC24E616199612FF8"),
    u64("0x7B42B3B3F6B3F145"), u64("0x42342121842115A5"), u64("0x25089C9C4A9C94D6"), u64("0x3CEE1E1E781EF066"),
    u64("0x8661434311432252"), u64("0x93B1C7C73BC776FC"), u64("0xE54FFCFCD7FCB32B"), u64("0x0824040410042014"),
    u64("0xA2E351515951B208"), u64("0x2F2599995E99BCC7"), u64("0xDA226D6DA96D4FC4"), u64("0x1A650D0D340D6839"),
    u64("0xE979FAFACFFA8335"), u64("0xA369DFDF5BDFB684"), u64("0xFCA97E7EE57ED79B"), u64("0x4819242490243DB4"),
    u64("0x76FE3B3BEC3BC5D7"), u64("0x4B9AABAB96AB313D"), u64("0x81F0CECE1FCE3ED1"), u64("0x2299111144118855"),
    u64("0x03838F8F068F0C89"), u64("0x9C044E4E254E4A6B"), u64("0x7366B7B7E6B7D151"), u64("0xCBE0EBEB8BEB0B60"),
    u64("0x78C13C3CF03CFDCC"), u64("0x1FFD81813E817CBF"), u64("0x354094946A94D4FE"), u64("0xF31CF7F7FBF7EB0C"),
    u64("0x6F18B9B9DEB9A167"), u64("0x268B13134C13985F"), u64("0x58512C2CB02C7D9C"), u64("0xBB05D3D36BD3D6B8"),
    u64("0xD38CE7E7BBE76B5C"), u64("0xDC396E6EA56E57CB"), u64("0x95AAC4C437C46EF3"), u64("0x061B03030C03180F"),
    u64("0xACDC565645568A13"), u64("0x885E44440D441A49"), u64("0xFEA07F7FE17FDF9E"), u64("0x4F88A9A99EA92137"),
    u64("0x54672A2AA82A4D82"), u64("0x6B0ABBBBD6BBB16D"), u64("0x9F87C1C123C146E2"), u64("0xA6F153535153A202"),
    u64("0xA572DCDC57DCAE8B"), u64("0x16530B0B2C0B5827"), u64("0x27019D9D4E9D9CD3"), u64("0xD82B6C6CAD6C47C1"),
    u64("0x62A43131C43195F5"), u64("0xE8F37474CD7487B9"), u64("0xF115F6F6FFF6E309"), u64("0x8C4C464605460A43"),
    u64("0x45A5ACAC8AAC0926"), u64("0x0FB589891E893C97"), u64("0x28B414145014A044"), u64("0xDFBAE1E1A3E15B42"),
    u64("0x2CA616165816B04E"), u64("0x74F73A3AE83ACDD2"), u64("0xD2066969B9696FD0"), u64("0x124109092409482D"),
    u64("0xE0D77070DD70A7AD"), u64("0x716FB6B6E2B6D954"), u64("0xBD1ED0D067D0CEB7"), u64("0xC7D6EDED93ED3B7E"),
    u64("0x85E2CCCC17CC2EDB"), u64("0x8468424215422A57"), u64("0x2D2C98985A98B4C2"), u64("0x55EDA4A4AAA4490E"),
    u64("0x50752828A0285D88"), u64("0xB8865C5C6D5CDA31"), u64("0xED6BF8F8C7F8933F"), u64("0x11C28686228644A4")
}

local C3 = {
    u64("0x7830D818186018C0"), u64("0xAF462623238C2305"), u64("0xF991B8C6C63FC67E"), u64("0x6FCDFBE8E887E813"),
    u64("0xA113CB878726874C"), u64("0x626D11B8B8DAB8A9"), u64("0x0502090101040108"), u64("0x6E9E0D4F4F214F42"),
    u64("0xEE6C9B3636D836AD"), u64("0x0451FFA6A6A2A659"), u64("0xBDB90CD2D26FD2DE"), u64("0x06F70EF5F5F3F5FB"),
    u64("0x80F2967979F979EF"), u64("0xCEDE306F6FA16F5F"), u64("0xEF3F6D91917E91FC"), u64("0x07A4F852525552AA"),
    u64("0xFDC04760609D6027"), u64("0x766535BCBCCABC89"), u64("0xCD2B379B9B569BAC"), u64("0x8C018A8E8E028E04"),
    u64("0x155BD2A3A3B6A371"), u64("0x3C186C0C0C300C60"), u64("0x8AF6847B7BF17BFF"), u64("0xE16A803535D435B5"),
    u64("0x693AF51D1D741DE8"), u64("0x47DDB3E0E0A7E053"), u64("0xACB321D7D77BD7F6"), u64("0xED999CC2C22FC25E"),
    u64("0x965C432E2EB82E6D"), u64("0x7A96294B4B314B62"), u64("0x21E15DFEFEDFFEA3"), u64("0x16AED55757415782"),
    u64("0x412ABD15155415A8"), u64("0xB6EEE87777C1779F"), u64("0xEB6E923737DC37A5"), u64("0x56D79EE5E5B3E57B"),
    u64("0xD923139F9F469F8C"), u64("0x17FD23F0F0E7F0D3"), u64("0x7F94204A4A354A6A"), u64("0x95A944DADA4FDA9E"),
    u64("0x25B0A258587D58FA"), u64("0xCA8FCFC9C903C906"), u64("0x8D527C2929A42955"), u64("0x22145A0A0A280A50"),
    u64("0x4F7F50B1B1FEB1E1"), u64("0x1A5DC9A0A0BAA069"), u64("0xDAD6146B6BB16B7F"), u64("0xAB17D985852E855C"),
    u64("0x73673CBDBDCEBD81"), u64("0x34BA8F5D5D695DD2"), u64("0x5020901010401080"), u64("0x03F507F4F4F7F4F3"),
    u64("0xC08BDDCBCB0BCB16"), u64("0xC67CD33E3EF83EED"), u64("0x110A2D0505140528"), u64("0xE6CE78676781671F"),
    u64("0x53D597E4E4B7E473"), u64("0xBB4E0227279C2725"), u64("0x5882734141194132"), u64("0x9D0BA78B8B168B2C"),
    u64("0x0153F6A7A7A6A751"), u64("0x94FAB27D7DE97DCF"), u64("0xFB374995956E95DC"), u64("0x9FAD56D8D847D88E"),
    u64("0x30EB70FBFBCBFB8B"), u64("0x71C1CDEEEE9FEE23"), u64("0x91F8BB7C7CED7CC7"), u64("0xE3CC716666856617"),
    u64("0x8EA77BDDDD53DDA6"), u64("0x4B2EAF17175C17B8"), u64("0x468E454747014702"), u64("0xDC211A9E9E429E84"),
    u64("0xC589D4CACA0FCA1E"), u64("0x995A582D2DB42D75"), u64("0x79632EBFBFC6BF91"), u64("0x1B0E3F07071C0738"),
    u64("0x2347ACADAD8EAD01"), u64("0x2FB4B05A5A755AEA"), u64("0xB51BEF838336836C"), u64("0xFF66B63333CC3385"),
    u64("0xF2C65C636391633F"), u64("0x0A04120202080210"), u64("0x384993AAAA92AA39"), u64("0xA8E2DE7171D971AF"),
    u64("0xCF8DC6C8C807C80E"), u64("0x7D32D119196419C8"), u64("0x70923B4949394972"), u64("0x9AAF5FD9D943D986"),
    u64("0x1DF931F2F2EFF2C3"), u64("0x48DBA8E3E3ABE34B"), u64("0x2AB6B95B5B715BE2"), u64("0x920DBC88881A8834"),
    u64("0xC8293E9A9A529AA4"), u64("0xBE4C0B262698262D"), u64("0xFA64BF3232C8328D"), u64("0x4A7D59B0B0FAB0E9"),
    u64("0x6ACFF2E9E983E91B"), u64("0x331E770F0F3C0F78"), u64("0xA6B733D5D573D5E6"), u64("0xBA1DF480803A8074"),
    u64("0x7C6127BEBEC2BE99"), u64("0xDE87EBCDCD13CD26"), u64("0xE468893434D034BD"), u64("0x75903248483D487A"),
    u64("0x24E354FFFFDBFFAB"), u64("0x8FF48D7A7AF57AF7"), u64("0xEA3D6490907A90F4"), u64("0x3EBE9D5F5F615FC2"),
    u64("0xA0403D202080201D"), u64("0xD5D00F6868BD6867"), u64("0x7234CA1A1A681AD0"), u64("0x2C41B7AEAE82AE19"),
    u64("0x5E757DB4B4EAB4C9"), u64("0x19A8CE54544D549A"), u64("0xE53B7F93937693EC"), u64("0xAA442F222288220D"),
    u64("0xE9C86364648D6407"), u64("0x12FF2AF1F1E3F1DB"), u64("0xA2E6CC7373D173BF"), u64("0x5A24821212481290"),
    u64("0x5D807A40401D403A"), u64("0x2810480808200840"), u64("0xE89B95C3C32BC356"), u64("0x7BC5DFECEC97EC33"),
    u64("0x90AB4DDBDB4BDB96"), u64("0x1F5FC0A1A1BEA161"), u64("0x8307918D8D0E8D1C"), u64("0xC97AC83D3DF43DF5"),
    u64("0xF1335B97976697CC"), u64("0x0000000000000000"), u64("0xD483F9CFCF1BCF36"), u64("0x87566E2B2BAC2B45"),
    u64("0xB3ECE17676C57697"), u64("0xB019E68282328264"), u64("0xA9B128D6D67FD6FE"), u64("0x7736C31B1B6C1BD8"),
    u64("0x5B7774B5B5EEB5C1"), u64("0x2943BEAFAF86AF11"), u64("0xDFD41D6A6AB56A77"), u64("0x0DA0EA50505D50BA"),
    u64("0x4C8A574545094512"), u64("0x18FB38F3F3EBF3CB"), u64("0xF060AD3030C0309D"), u64("0x74C3C4EFEF9BEF2B"),
    u64("0xC37EDA3F3FFC3FE5"), u64("0x1CAAC75555495592"), u64("0x1059DBA2A2B2A279"), u64("0x65C9E9EAEA8FEA03"),
    u64("0xECCA6A656589650F"), u64("0x686903BABAD2BAB9"), u64("0x935E4A2F2FBC2F65"), u64("0xE79D8EC0C027C04E"),
    u64("0x81A160DEDE5FDEBE"), u64("0x6C38FC1C1C701CE0"), u64("0x2EE746FDFDD3FDBB"), u64("0x649A1F4D4D294D52"),
    u64("0xE0397692927292E4"), u64("0xBCEAFA7575C9758F"), u64("0x1E0C360606180630"), u64("0x9809AE8A8A128A24"),
    u64("0x40794BB2B2F2B2F9"), u64("0x59D185E6E6BFE663"), u64("0x361C7E0E0E380E70"), u64("0x633EE71F1F7C1FF8"),
    u64("0xF7C4556262956237"), u64("0xA3B53AD4D477D4EE"), u64("0x324D81A8A89AA829"), u64("0xF4315296966296C4"),
    u64("0x3AEF62F9F9C3F99B"), u64("0xF697A3C5C533C566"), u64("0xB14A102525942535"), u64("0x20B2AB59597959F2"),
    u64("0xAE15D084842A8454"), u64("0xA7E4C57272D572B7"), u64("0xDD72EC3939E439D5"), u64("0x6198164C4C2D4C5A"),
    u64("0x3BBC945E5E655ECA"), u64("0x85F09F7878FD78E7"), u64("0xD870E53838E038DD"), u64("0x8605988C8C0A8C14"),
    u64("0xB2BF17D1D163D1C6"), u64("0x0B57E4A5A5AEA541"), u64("0x4DD9A1E2E2AFE243"), u64("0xF8C24E616199612F"),
    u64("0x457B42B3B3F6B3F1"), u64("0xA542342121842115"), u64("0xD625089C9C4A9C94"), u64("0x663CEE1E1E781EF0"),
    u64("0x5286614343114322"), u64("0xFC93B1C7C73BC776"), u64("0x2BE54FFCFCD7FCB3"), u64("0x1408240404100420"),
    u64("0x08A2E351515951B2"), u64("0xC72F2599995E99BC"), u64("0xC4DA226D6DA96D4F"), u64("0x391A650D0D340D68"),
    u64("0x35E979FAFACFFA83"), u64("0x84A369DFDF5BDFB6"), u64("0x9BFCA97E7EE57ED7"), u64("0xB44819242490243D"),
    u64("0xD776FE3B3BEC3BC5"), u64("0x3D4B9AABAB96AB31"), u64("0xD181F0CECE1FCE3E"), u64("0x5522991111441188"),
    u64("0x8903838F8F068F0C"), u64("0x6B9C044E4E254E4A"), u64("0x517366B7B7E6B7D1"), u64("0x60CBE0EBEB8BEB0B"),
    u64("0xCC78C13C3CF03CFD"), u64("0xBF1FFD81813E817C"), u64("0xFE354094946A94D4"), u64("0x0CF31CF7F7FBF7EB"),
    u64("0x676F18B9B9DEB9A1"), u64("0x5F268B13134C1398"), u64("0x9C58512C2CB02C7D"), u64("0xB8BB05D3D36BD3D6"),
    u64("0x5CD38CE7E7BBE76B"), u64("0xCBDC396E6EA56E57"), u64("0xF395AAC4C437C46E"), u64("0x0F061B03030C0318"),
    u64("0x13ACDC565645568A"), u64("0x49885E44440D441A"), u64("0x9EFEA07F7FE17FDF"), u64("0x374F88A9A99EA921"),
    u64("0x8254672A2AA82A4D"), u64("0x6D6B0ABBBBD6BBB1"), u64("0xE29F87C1C123C146"), u64("0x02A6F153535153A2"),
    u64("0x8BA572DCDC57DCAE"), u64("0x2716530B0B2C0B58"), u64("0xD327019D9D4E9D9C"), u64("0xC1D82B6C6CAD6C47"),
    u64("0xF562A43131C43195"), u64("0xB9E8F37474CD7487"), u64("0x09F115F6F6FFF6E3"), u64("0x438C4C464605460A"),
    u64("0x2645A5ACAC8AAC09"), u64("0x970FB589891E893C"), u64("0x4428B414145014A0"), u64("0x42DFBAE1E1A3E15B"),
    u64("0x4E2CA616165816B0"), u64("0xD274F73A3AE83ACD"), u64("0xD0D2066969B9696F"), u64("0x2D12410909240948"),
    u64("0xADE0D77070DD70A7"), u64("0x54716FB6B6E2B6D9"), u64("0xB7BD1ED0D067D0CE"), u64("0x7EC7D6EDED93ED3B"),
    u64("0xDB85E2CCCC17CC2E"), u64("0x578468424215422A"), u64("0xC22D2C98985A98B4"), u64("0x0E55EDA4A4AAA449"),
    u64("0x8850752828A0285D"), u64("0x31B8865C5C6D5CDA"), u64("0x3FED6BF8F8C7F893"), u64("0xA411C28686228644")
}

local C4 = {
    u64("0xC07830D818186018"), u64("0x05AF462623238C23"), u64("0x7EF991B8C6C63FC6"), u64("0x136FCDFBE8E887E8"),
    u64("0x4CA113CB87872687"), u64("0xA9626D11B8B8DAB8"), u64("0x0805020901010401"), u64("0x426E9E0D4F4F214F"),
    u64("0xADEE6C9B3636D836"), u64("0x590451FFA6A6A2A6"), u64("0xDEBDB90CD2D26FD2"), u64("0xFB06F70EF5F5F3F5"),
    u64("0xEF80F2967979F979"), u64("0x5FCEDE306F6FA16F"), u64("0xFCEF3F6D91917E91"), u64("0xAA07A4F852525552"),
    u64("0x27FDC04760609D60"), u64("0x89766535BCBCCABC"), u64("0xACCD2B379B9B569B"), u64("0x048C018A8E8E028E"),
    u64("0x71155BD2A3A3B6A3"), u64("0x603C186C0C0C300C"), u64("0xFF8AF6847B7BF17B"), u64("0xB5E16A803535D435"),
    u64("0xE8693AF51D1D741D"), u64("0x5347DDB3E0E0A7E0"), u64("0xF6ACB321D7D77BD7"), u64("0x5EED999CC2C22FC2"),
    u64("0x6D965C432E2EB82E"), u64("0x627A96294B4B314B"), u64("0xA321E15DFEFEDFFE"), u64("0x8216AED557574157"),
    u64("0xA8412ABD15155415"), u64("0x9FB6EEE87777C177"), u64("0xA5EB6E923737DC37"), u64("0x7B56D79EE5E5B3E5"),
    u64("0x8CD923139F9F469F"), u64("0xD317FD23F0F0E7F0"), u64("0x6A7F94204A4A354A"), u64("0x9E95A944DADA4FDA"),
    u64("0xFA25B0A258587D58"), u64("0x06CA8FCFC9C903C9"), u64("0x558D527C2929A429"), u64("0x5022145A0A0A280A"),
    u64("0xE14F7F50B1B1FEB1"), u64("0x691A5DC9A0A0BAA0"), u64("0x7FDAD6146B6BB16B"), u64("0x5CAB17D985852E85"),
    u64("0x8173673CBDBDCEBD"), u64("0xD234BA8F5D5D695D"), u64("0x8050209010104010"), u64("0xF303F507F4F4F7F4"),
    u64("0x16C08BDDCBCB0BCB"), u64("0xEDC67CD33E3EF83E"), u64("0x28110A2D05051405"), u64("0x1FE6CE7867678167"),
    u64("0x7353D597E4E4B7E4"), u64("0x25BB4E0227279C27"), u64("0x3258827341411941"), u64("0x2C9D0BA78B8B168B"),
    u64("0x510153F6A7A7A6A7"), u64("0xCF94FAB27D7DE97D"), u64("0xDCFB374995956E95"), u64("0x8E9FAD56D8D847D8"),
    u64("0x8B30EB70FBFBCBFB"), u64("0x2371C1CDEEEE9FEE"), u64("0xC791F8BB7C7CED7C"), u64("0x17E3CC7166668566"),
    u64("0xA68EA77BDDDD53DD"), u64("0xB84B2EAF17175C17"), u64("0x02468E4547470147"), u64("0x84DC211A9E9E429E"),
    u64("0x1EC589D4CACA0FCA"), u64("0x75995A582D2DB42D"), u64("0x9179632EBFBFC6BF"), u64("0x381B0E3F07071C07"),
    u64("0x012347ACADAD8EAD"), u64("0xEA2FB4B05A5A755A"), u64("0x6CB51BEF83833683"), u64("0x85FF66B63333CC33"),
    u64("0x3FF2C65C63639163"), u64("0x100A041202020802"), u64("0x39384993AAAA92AA"), u64("0xAFA8E2DE7171D971"),
    u64("0x0ECF8DC6C8C807C8"), u64("0xC87D32D119196419"), u64("0x7270923B49493949"), u64("0x869AAF5FD9D943D9"),
    u64("0xC31DF931F2F2EFF2"), u64("0x4B48DBA8E3E3ABE3"), u64("0xE22AB6B95B5B715B"), u64("0x34920DBC88881A88"),
    u64("0xA4C8293E9A9A529A"), u64("0x2DBE4C0B26269826"), u64("0x8DFA64BF3232C832"), u64("0xE94A7D59B0B0FAB0"),
    u64("0x1B6ACFF2E9E983E9"), u64("0x78331E770F0F3C0F"), u64("0xE6A6B733D5D573D5"), u64("0x74BA1DF480803A80"),
    u64("0x997C6127BEBEC2BE"), u64("0x26DE87EBCDCD13CD"), u64("0xBDE468893434D034"), u64("0x7A75903248483D48"),
    u64("0xAB24E354FFFFDBFF"), u64("0xF78FF48D7A7AF57A"), u64("0xF4EA3D6490907A90"), u64("0xC23EBE9D5F5F615F"),
    u64("0x1DA0403D20208020"), u64("0x67D5D00F6868BD68"), u64("0xD07234CA1A1A681A"), u64("0x192C41B7AEAE82AE"),
    u64("0xC95E757DB4B4EAB4"), u64("0x9A19A8CE54544D54"), u64("0xECE53B7F93937693"), u64("0x0DAA442F22228822"),
    u64("0x07E9C86364648D64"), u64("0xDB12FF2AF1F1E3F1"), u64("0xBFA2E6CC7373D173"), u64("0x905A248212124812"),
    u64("0x3A5D807A40401D40"), u64("0x4028104808082008"), u64("0x56E89B95C3C32BC3"), u64("0x337BC5DFECEC97EC"),
    u64("0x9690AB4DDBDB4BDB"), u64("0x611F5FC0A1A1BEA1"), u64("0x1C8307918D8D0E8D"), u64("0xF5C97AC83D3DF43D"),
    u64("0xCCF1335B97976697"), u64("0x0000000000000000"), u64("0x36D483F9CFCF1BCF"), u64("0x4587566E2B2BAC2B"),
    u64("0x97B3ECE17676C576"), u64("0x64B019E682823282"), u64("0xFEA9B128D6D67FD6"), u64("0xD87736C31B1B6C1B"),
    u64("0xC15B7774B5B5EEB5"), u64("0x112943BEAFAF86AF"), u64("0x77DFD41D6A6AB56A"), u64("0xBA0DA0EA50505D50"),
    u64("0x124C8A5745450945"), u64("0xCB18FB38F3F3EBF3"), u64("0x9DF060AD3030C030"), u64("0x2B74C3C4EFEF9BEF"),
    u64("0xE5C37EDA3F3FFC3F"), u64("0x921CAAC755554955"), u64("0x791059DBA2A2B2A2"), u64("0x0365C9E9EAEA8FEA"),
    u64("0x0FECCA6A65658965"), u64("0xB9686903BABAD2BA"), u64("0x65935E4A2F2FBC2F"), u64("0x4EE79D8EC0C027C0"),
    u64("0xBE81A160DEDE5FDE"), u64("0xE06C38FC1C1C701C"), u64("0xBB2EE746FDFDD3FD"), u64("0x52649A1F4D4D294D"),
    u64("0xE4E0397692927292"), u64("0x8FBCEAFA7575C975"), u64("0x301E0C3606061806"), u64("0x249809AE8A8A128A"),
    u64("0xF940794BB2B2F2B2"), u64("0x6359D185E6E6BFE6"), u64("0x70361C7E0E0E380E"), u64("0xF8633EE71F1F7C1F"),
    u64("0x37F7C45562629562"), u64("0xEEA3B53AD4D477D4"), u64("0x29324D81A8A89AA8"), u64("0xC4F4315296966296"),
    u64("0x9B3AEF62F9F9C3F9"), u64("0x66F697A3C5C533C5"), u64("0x35B14A1025259425"), u64("0xF220B2AB59597959"),
    u64("0x54AE15D084842A84"), u64("0xB7A7E4C57272D572"), u64("0xD5DD72EC3939E439"), u64("0x5A6198164C4C2D4C"),
    u64("0xCA3BBC945E5E655E"), u64("0xE785F09F7878FD78"), u64("0xDDD870E53838E038"), u64("0x148605988C8C0A8C"),
    u64("0xC6B2BF17D1D163D1"), u64("0x410B57E4A5A5AEA5"), u64("0x434DD9A1E2E2AFE2"), u64("0x2FF8C24E61619961"),
    u64("0xF1457B42B3B3F6B3"), u64("0x15A5423421218421"), u64("0x94D625089C9C4A9C"), u64("0xF0663CEE1E1E781E"),
    u64("0x2252866143431143"), u64("0x76FC93B1C7C73BC7"), u64("0xB32BE54FFCFCD7FC"), u64("0x2014082404041004"),
    u64("0xB208A2E351515951"), u64("0xBCC72F2599995E99"), u64("0x4FC4DA226D6DA96D"), u64("0x68391A650D0D340D"),
    u64("0x8335E979FAFACFFA"), u64("0xB684A369DFDF5BDF"), u64("0xD79BFCA97E7EE57E"), u64("0x3DB4481924249024"),
    u64("0xC5D776FE3B3BEC3B"), u64("0x313D4B9AABAB96AB"), u64("0x3ED181F0CECE1FCE"), u64("0x8855229911114411"),
    u64("0x0C8903838F8F068F"), u64("0x4A6B9C044E4E254E"), u64("0xD1517366B7B7E6B7"), u64("0x0B60CBE0EBEB8BEB"),
    u64("0xFDCC78C13C3CF03C"), u64("0x7CBF1FFD81813E81"), u64("0xD4FE354094946A94"), u64("0xEB0CF31CF7F7FBF7"),
    u64("0xA1676F18B9B9DEB9"), u64("0x985F268B13134C13"), u64("0x7D9C58512C2CB02C"), u64("0xD6B8BB05D3D36BD3"),
    u64("0x6B5CD38CE7E7BBE7"), u64("0x57CBDC396E6EA56E"), u64("0x6EF395AAC4C437C4"), u64("0x180F061B03030C03"),
    u64("0x8A13ACDC56564556"), u64("0x1A49885E44440D44"), u64("0xDF9EFEA07F7FE17F"), u64("0x21374F88A9A99EA9"),
    u64("0x4D8254672A2AA82A"), u64("0xB16D6B0ABBBBD6BB"), u64("0x46E29F87C1C123C1"), u64("0xA202A6F153535153"),
    u64("0xAE8BA572DCDC57DC"), u64("0x582716530B0B2C0B"), u64("0x9CD327019D9D4E9D"), u64("0x47C1D82B6C6CAD6C"),
    u64("0x95F562A43131C431"), u64("0x87B9E8F37474CD74"), u64("0xE309F115F6F6FFF6"), u64("0x0A438C4C46460546"),
    u64("0x092645A5ACAC8AAC"), u64("0x3C970FB589891E89"), u64("0xA04428B414145014"), u64("0x5B42DFBAE1E1A3E1"),
    u64("0xB04E2CA616165816"), u64("0xCDD274F73A3AE83A"), u64("0x6FD0D2066969B969"), u64("0x482D124109092409"),
    u64("0xA7ADE0D77070DD70"), u64("0xD954716FB6B6E2B6"), u64("0xCEB7BD1ED0D067D0"), u64("0x3B7EC7D6EDED93ED"),
    u64("0x2EDB85E2CCCC17CC"), u64("0x2A57846842421542"), u64("0xB4C22D2C98985A98"), u64("0x490E55EDA4A4AAA4"),
    u64("0x5D8850752828A028"), u64("0xDA31B8865C5C6D5C"), u64("0x933FED6BF8F8C7F8"), u64("0x44A411C286862286")
}

local C5 = {
    u64("0x18C07830D8181860"), u64("0x2305AF462623238C"), u64("0xC67EF991B8C6C63F"), u64("0xE8136FCDFBE8E887"),
    u64("0x874CA113CB878726"), u64("0xB8A9626D11B8B8DA"), u64("0x0108050209010104"), u64("0x4F426E9E0D4F4F21"),
    u64("0x36ADEE6C9B3636D8"), u64("0xA6590451FFA6A6A2"), u64("0xD2DEBDB90CD2D26F"), u64("0xF5FB06F70EF5F5F3"),
    u64("0x79EF80F2967979F9"), u64("0x6F5FCEDE306F6FA1"), u64("0x91FCEF3F6D91917E"), u64("0x52AA07A4F8525255"),
    u64("0x6027FDC04760609D"), u64("0xBC89766535BCBCCA"), u64("0x9BACCD2B379B9B56"), u64("0x8E048C018A8E8E02"),
    u64("0xA371155BD2A3A3B6"), u64("0x0C603C186C0C0C30"), u64("0x7BFF8AF6847B7BF1"), u64("0x35B5E16A803535D4"),
    u64("0x1DE8693AF51D1D74"), u64("0xE05347DDB3E0E0A7"), u64("0xD7F6ACB321D7D77B"), u64("0xC25EED999CC2C22F"),
    u64("0x2E6D965C432E2EB8"), u64("0x4B627A96294B4B31"), u64("0xFEA321E15DFEFEDF"), u64("0x578216AED5575741"),
    u64("0x15A8412ABD151554"), u64("0x779FB6EEE87777C1"), u64("0x37A5EB6E923737DC"), u64("0xE57B56D79EE5E5B3"),
    u64("0x9F8CD923139F9F46"), u64("0xF0D317FD23F0F0E7"), u64("0x4A6A7F94204A4A35"), u64("0xDA9E95A944DADA4F"),
    u64("0x58FA25B0A258587D"), u64("0xC906CA8FCFC9C903"), u64("0x29558D527C2929A4"), u64("0x0A5022145A0A0A28"),
    u64("0xB1E14F7F50B1B1FE"), u64("0xA0691A5DC9A0A0BA"), u64("0x6B7FDAD6146B6BB1"), u64("0x855CAB17D985852E"),
    u64("0xBD8173673CBDBDCE"), u64("0x5DD234BA8F5D5D69"), u64("0x1080502090101040"), u64("0xF4F303F507F4F4F7"),
    u64("0xCB16C08BDDCBCB0B"), u64("0x3EEDC67CD33E3EF8"), u64("0x0528110A2D050514"), u64("0x671FE6CE78676781"),
    u64("0xE47353D597E4E4B7"), u64("0x2725BB4E0227279C"), u64("0x4132588273414119"), u64("0x8B2C9D0BA78B8B16"),
    u64("0xA7510153F6A7A7A6"), u64("0x7DCF94FAB27D7DE9"), u64("0x95DCFB374995956E"), u64("0xD88E9FAD56D8D847"),
    u64("0xFB8B30EB70FBFBCB"), u64("0xEE2371C1CDEEEE9F"), u64("0x7CC791F8BB7C7CED"), u64("0x6617E3CC71666685"),
    u64("0xDDA68EA77BDDDD53"), u64("0x17B84B2EAF17175C"), u64("0x4702468E45474701"), u64("0x9E84DC211A9E9E42"),
    u64("0xCA1EC589D4CACA0F"), u64("0x2D75995A582D2DB4"), u64("0xBF9179632EBFBFC6"), u64("0x07381B0E3F07071C"),
    u64("0xAD012347ACADAD8E"), u64("0x5AEA2FB4B05A5A75"), u64("0x836CB51BEF838336"), u64("0x3385FF66B63333CC"),
    u64("0x633FF2C65C636391"), u64("0x02100A0412020208"), u64("0xAA39384993AAAA92"), u64("0x71AFA8E2DE7171D9"),
    u64("0xC80ECF8DC6C8C807"), u64("0x19C87D32D1191964"), u64("0x497270923B494939"), u64("0xD9869AAF5FD9D943"),
    u64("0xF2C31DF931F2F2EF"), u64("0xE34B48DBA8E3E3AB"), u64("0x5BE22AB6B95B5B71"), u64("0x8834920DBC88881A"),
    u64("0x9AA4C8293E9A9A52"), u64("0x262DBE4C0B262698"), u64("0x328DFA64BF3232C8"), u64("0xB0E94A7D59B0B0FA"),
    u64("0xE91B6ACFF2E9E983"), u64("0x0F78331E770F0F3C"), u64("0xD5E6A6B733D5D573"), u64("0x8074BA1DF480803A"),
    u64("0xBE997C6127BEBEC2"), u64("0xCD26DE87EBCDCD13"), u64("0x34BDE468893434D0"), u64("0x487A75903248483D"),
    u64("0xFFAB24E354FFFFDB"), u64("0x7AF78FF48D7A7AF5"), u64("0x90F4EA3D6490907A"), u64("0x5FC23EBE9D5F5F61"),
    u64("0x201DA0403D202080"), u64("0x6867D5D00F6868BD"), u64("0x1AD07234CA1A1A68"), u64("0xAE192C41B7AEAE82"),
    u64("0xB4C95E757DB4B4EA"), u64("0x549A19A8CE54544D"), u64("0x93ECE53B7F939376"), u64("0x220DAA442F222288"),
    u64("0x6407E9C86364648D"), u64("0xF1DB12FF2AF1F1E3"), u64("0x73BFA2E6CC7373D1"), u64("0x12905A2482121248"),
    u64("0x403A5D807A40401D"), u64("0x0840281048080820"), u64("0xC356E89B95C3C32B"), u64("0xEC337BC5DFECEC97"),
    u64("0xDB9690AB4DDBDB4B"), u64("0xA1611F5FC0A1A1BE"), u64("0x8D1C8307918D8D0E"), u64("0x3DF5C97AC83D3DF4"),
    u64("0x97CCF1335B979766"), u64("0x0000000000000000"), u64("0xCF36D483F9CFCF1B"), u64("0x2B4587566E2B2BAC"),
    u64("0x7697B3ECE17676C5"), u64("0x8264B019E6828232"), u64("0xD6FEA9B128D6D67F"), u64("0x1BD87736C31B1B6C"),
    u64("0xB5C15B7774B5B5EE"), u64("0xAF112943BEAFAF86"), u64("0x6A77DFD41D6A6AB5"), u64("0x50BA0DA0EA50505D"),
    u64("0x45124C8A57454509"), u64("0xF3CB18FB38F3F3EB"), u64("0x309DF060AD3030C0"), u64("0xEF2B74C3C4EFEF9B"),
    u64("0x3FE5C37EDA3F3FFC"), u64("0x55921CAAC7555549"), u64("0xA2791059DBA2A2B2"), u64("0xEA0365C9E9EAEA8F"),
    u64("0x650FECCA6A656589"), u64("0xBAB9686903BABAD2"), u64("0x2F65935E4A2F2FBC"), u64("0xC04EE79D8EC0C027"),
    u64("0xDEBE81A160DEDE5F"), u64("0x1CE06C38FC1C1C70"), u64("0xFDBB2EE746FDFDD3"), u64("0x4D52649A1F4D4D29"),
    u64("0x92E4E03976929272"), u64("0x758FBCEAFA7575C9"), u64("0x06301E0C36060618"), u64("0x8A249809AE8A8A12"),
    u64("0xB2F940794BB2B2F2"), u64("0xE66359D185E6E6BF"), u64("0x0E70361C7E0E0E38"), u64("0x1FF8633EE71F1F7C"),
    u64("0x6237F7C455626295"), u64("0xD4EEA3B53AD4D477"), u64("0xA829324D81A8A89A"), u64("0x96C4F43152969662"),
    u64("0xF99B3AEF62F9F9C3"), u64("0xC566F697A3C5C533"), u64("0x2535B14A10252594"), u64("0x59F220B2AB595979"),
    u64("0x8454AE15D084842A"), u64("0x72B7A7E4C57272D5"), u64("0x39D5DD72EC3939E4"), u64("0x4C5A6198164C4C2D"),
    u64("0x5ECA3BBC945E5E65"), u64("0x78E785F09F7878FD"), u64("0x38DDD870E53838E0"), u64("0x8C148605988C8C0A"),
    u64("0xD1C6B2BF17D1D163"), u64("0xA5410B57E4A5A5AE"), u64("0xE2434DD9A1E2E2AF"), u64("0x612FF8C24E616199"),
    u64("0xB3F1457B42B3B3F6"), u64("0x2115A54234212184"), u64("0x9C94D625089C9C4A"), u64("0x1EF0663CEE1E1E78"),
    u64("0x4322528661434311"), u64("0xC776FC93B1C7C73B"), u64("0xFCB32BE54FFCFCD7"), u64("0x0420140824040410"),
    u64("0x51B208A2E3515159"), u64("0x99BCC72F2599995E"), u64("0x6D4FC4DA226D6DA9"), u64("0x0D68391A650D0D34"),
    u64("0xFA8335E979FAFACF"), u64("0xDFB684A369DFDF5B"), u64("0x7ED79BFCA97E7EE5"), u64("0x243DB44819242490"),
    u64("0x3BC5D776FE3B3BEC"), u64("0xAB313D4B9AABAB96"), u64("0xCE3ED181F0CECE1F"), u64("0x1188552299111144"),
    u64("0x8F0C8903838F8F06"), u64("0x4E4A6B9C044E4E25"), u64("0xB7D1517366B7B7E6"), u64("0xEB0B60CBE0EBEB8B"),
    u64("0x3CFDCC78C13C3CF0"), u64("0x817CBF1FFD81813E"), u64("0x94D4FE354094946A"), u64("0xF7EB0CF31CF7F7FB"),
    u64("0xB9A1676F18B9B9DE"), u64("0x13985F268B13134C"), u64("0x2C7D9C58512C2CB0"), u64("0xD3D6B8BB05D3D36B"),
    u64("0xE76B5CD38CE7E7BB"), u64("0x6E57CBDC396E6EA5"), u64("0xC46EF395AAC4C437"), u64("0x03180F061B03030C"),
    u64("0x568A13ACDC565645"), u64("0x441A49885E44440D"), u64("0x7FDF9EFEA07F7FE1"), u64("0xA921374F88A9A99E"),
    u64("0x2A4D8254672A2AA8"), u64("0xBBB16D6B0ABBBBD6"), u64("0xC146E29F87C1C123"), u64("0x53A202A6F1535351"),
    u64("0xDCAE8BA572DCDC57"), u64("0x0B582716530B0B2C"), u64("0x9D9CD327019D9D4E"), u64("0x6C47C1D82B6C6CAD"),
    u64("0x3195F562A43131C4"), u64("0x7487B9E8F37474CD"), u64("0xF6E309F115F6F6FF"), u64("0x460A438C4C464605"),
    u64("0xAC092645A5ACAC8A"), u64("0x893C970FB589891E"), u64("0x14A04428B4141450"), u64("0xE15B42DFBAE1E1A3"),
    u64("0x16B04E2CA6161658"), u64("0x3ACDD274F73A3AE8"), u64("0x696FD0D2066969B9"), u64("0x09482D1241090924"),
    u64("0x70A7ADE0D77070DD"), u64("0xB6D954716FB6B6E2"), u64("0xD0CEB7BD1ED0D067"), u64("0xED3B7EC7D6EDED93"),
    u64("0xCC2EDB85E2CCCC17"), u64("0x422A578468424215"), u64("0x98B4C22D2C98985A"), u64("0xA4490E55EDA4A4AA"),
    u64("0x285D8850752828A0"), u64("0x5CDA31B8865C5C6D"), u64("0xF8933FED6BF8F8C7"), u64("0x8644A411C2868622")
}

local C6 = {
    u64("0x6018C07830D81818"), u64("0x8C2305AF46262323"), u64("0x3FC67EF991B8C6C6"), u64("0x87E8136FCDFBE8E8"),
    u64("0x26874CA113CB8787"), u64("0xDAB8A9626D11B8B8"), u64("0x0401080502090101"), u64("0x214F426E9E0D4F4F"),
    u64("0xD836ADEE6C9B3636"), u64("0xA2A6590451FFA6A6"), u64("0x6FD2DEBDB90CD2D2"), u64("0xF3F5FB06F70EF5F5"),
    u64("0xF979EF80F2967979"), u64("0xA16F5FCEDE306F6F"), u64("0x7E91FCEF3F6D9191"), u64("0x5552AA07A4F85252"),
    u64("0x9D6027FDC0476060"), u64("0xCABC89766535BCBC"), u64("0x569BACCD2B379B9B"), u64("0x028E048C018A8E8E"),
    u64("0xB6A371155BD2A3A3"), u64("0x300C603C186C0C0C"), u64("0xF17BFF8AF6847B7B"), u64("0xD435B5E16A803535"),
    u64("0x741DE8693AF51D1D"), u64("0xA7E05347DDB3E0E0"), u64("0x7BD7F6ACB321D7D7"), u64("0x2FC25EED999CC2C2"),
    u64("0xB82E6D965C432E2E"), u64("0x314B627A96294B4B"), u64("0xDFFEA321E15DFEFE"), u64("0x41578216AED55757"),
    u64("0x5415A8412ABD1515"), u64("0xC1779FB6EEE87777"), u64("0xDC37A5EB6E923737"), u64("0xB3E57B56D79EE5E5"),
    u64("0x469F8CD923139F9F"), u64("0xE7F0D317FD23F0F0"), u64("0x354A6A7F94204A4A"), u64("0x4FDA9E95A944DADA"),
    u64("0x7D58FA25B0A25858"), u64("0x03C906CA8FCFC9C9"), u64("0xA429558D527C2929"), u64("0x280A5022145A0A0A"),
    u64("0xFEB1E14F7F50B1B1"), u64("0xBAA0691A5DC9A0A0"), u64("0xB16B7FDAD6146B6B"), u64("0x2E855CAB17D98585"),
    u64("0xCEBD8173673CBDBD"), u64("0x695DD234BA8F5D5D"), u64("0x4010805020901010"), u64("0xF7F4F303F507F4F4"),
    u64("0x0BCB16C08BDDCBCB"), u64("0xF83EEDC67CD33E3E"), u64("0x140528110A2D0505"), u64("0x81671FE6CE786767"),
    u64("0xB7E47353D597E4E4"), u64("0x9C2725BB4E022727"), u64("0x1941325882734141"), u64("0x168B2C9D0BA78B8B"),
    u64("0xA6A7510153F6A7A7"), u64("0xE97DCF94FAB27D7D"), u64("0x6E95DCFB37499595"), u64("0x47D88E9FAD56D8D8"),
    u64("0xCBFB8B30EB70FBFB"), u64("0x9FEE2371C1CDEEEE"), u64("0xED7CC791F8BB7C7C"), u64("0x856617E3CC716666"),
    u64("0x53DDA68EA77BDDDD"), u64("0x5C17B84B2EAF1717"), u64("0x014702468E454747"), u64("0x429E84DC211A9E9E"),
    u64("0x0FCA1EC589D4CACA"), u64("0xB42D75995A582D2D"), u64("0xC6BF9179632EBFBF"), u64("0x1C07381B0E3F0707"),
    u64("0x8EAD012347ACADAD"), u64("0x755AEA2FB4B05A5A"), u64("0x36836CB51BEF8383"), u64("0xCC3385FF66B63333"),
    u64("0x91633FF2C65C6363"), u64("0x0802100A04120202"), u64("0x92AA39384993AAAA"), u64("0xD971AFA8E2DE7171"),
    u64("0x07C80ECF8DC6C8C8"), u64("0x6419C87D32D11919"), u64("0x39497270923B4949"), u64("0x43D9869AAF5FD9D9"),
    u64("0xEFF2C31DF931F2F2"), u64("0xABE34B48DBA8E3E3"), u64("0x715BE22AB6B95B5B"), u64("0x1A8834920DBC8888"),
    u64("0x529AA4C8293E9A9A"), u64("0x98262DBE4C0B2626"), u64("0xC8328DFA64BF3232"), u64("0xFAB0E94A7D59B0B0"),
    u64("0x83E91B6ACFF2E9E9"), u64("0x3C0F78331E770F0F"), u64("0x73D5E6A6B733D5D5"), u64("0x3A8074BA1DF48080"),
    u64("0xC2BE997C6127BEBE"), u64("0x13CD26DE87EBCDCD"), u64("0xD034BDE468893434"), u64("0x3D487A7590324848"),
    u64("0xDBFFAB24E354FFFF"), u64("0xF57AF78FF48D7A7A"), u64("0x7A90F4EA3D649090"), u64("0x615FC23EBE9D5F5F"),
    u64("0x80201DA0403D2020"), u64("0xBD6867D5D00F6868"), u64("0x681AD07234CA1A1A"), u64("0x82AE192C41B7AEAE"),
    u64("0xEAB4C95E757DB4B4"), u64("0x4D549A19A8CE5454"), u64("0x7693ECE53B7F9393"), u64("0x88220DAA442F2222"),
    u64("0x8D6407E9C8636464"), u64("0xE3F1DB12FF2AF1F1"), u64("0xD173BFA2E6CC7373"), u64("0x4812905A24821212"),
    u64("0x1D403A5D807A4040"), u64("0x2008402810480808"), u64("0x2BC356E89B95C3C3"), u64("0x97EC337BC5DFECEC"),
    u64("0x4BDB9690AB4DDBDB"), u64("0xBEA1611F5FC0A1A1"), u64("0x0E8D1C8307918D8D"), u64("0xF43DF5C97AC83D3D"),
    u64("0x6697CCF1335B9797"), u64("0x0000000000000000"), u64("0x1BCF36D483F9CFCF"), u64("0xAC2B4587566E2B2B"),
    u64("0xC57697B3ECE17676"), u64("0x328264B019E68282"), u64("0x7FD6FEA9B128D6D6"), u64("0x6C1BD87736C31B1B"),
    u64("0xEEB5C15B7774B5B5"), u64("0x86AF112943BEAFAF"), u64("0xB56A77DFD41D6A6A"), u64("0x5D50BA0DA0EA5050"),
    u64("0x0945124C8A574545"), u64("0xEBF3CB18FB38F3F3"), u64("0xC0309DF060AD3030"), u64("0x9BEF2B74C3C4EFEF"),
    u64("0xFC3FE5C37EDA3F3F"), u64("0x4955921CAAC75555"), u64("0xB2A2791059DBA2A2"), u64("0x8FEA0365C9E9EAEA"),
    u64("0x89650FECCA6A6565"), u64("0xD2BAB9686903BABA"), u64("0xBC2F65935E4A2F2F"), u64("0x27C04EE79D8EC0C0"),
    u64("0x5FDEBE81A160DEDE"), u64("0x701CE06C38FC1C1C"), u64("0xD3FDBB2EE746FDFD"), u64("0x294D52649A1F4D4D"),
    u64("0x7292E4E039769292"), u64("0xC9758FBCEAFA7575"), u64("0x1806301E0C360606"), u64("0x128A249809AE8A8A"),
    u64("0xF2B2F940794BB2B2"), u64("0xBFE66359D185E6E6"), u64("0x380E70361C7E0E0E"), u64("0x7C1FF8633EE71F1F"),
    u64("0x956237F7C4556262"), u64("0x77D4EEA3B53AD4D4"), u64("0x9AA829324D81A8A8"), u64("0x6296C4F431529696"),
    u64("0xC3F99B3AEF62F9F9"), u64("0x33C566F697A3C5C5"), u64("0x942535B14A102525"), u64("0x7959F220B2AB5959"),
    u64("0x2A8454AE15D08484"), u64("0xD572B7A7E4C57272"), u64("0xE439D5DD72EC3939"), u64("0x2D4C5A6198164C4C"),
    u64("0x655ECA3BBC945E5E"), u64("0xFD78E785F09F7878"), u64("0xE038DDD870E53838"), u64("0x0A8C148605988C8C"),
    u64("0x63D1C6B2BF17D1D1"), u64("0xAEA5410B57E4A5A5"), u64("0xAFE2434DD9A1E2E2"), u64("0x99612FF8C24E6161"),
    u64("0xF6B3F1457B42B3B3"), u64("0x842115A542342121"), u64("0x4A9C94D625089C9C"), u64("0x781EF0663CEE1E1E"),
    u64("0x1143225286614343"), u64("0x3BC776FC93B1C7C7"), u64("0xD7FCB32BE54FFCFC"), u64("0x1004201408240404"),
    u64("0x5951B208A2E35151"), u64("0x5E99BCC72F259999"), u64("0xA96D4FC4DA226D6D"), u64("0x340D68391A650D0D"),
    u64("0xCFFA8335E979FAFA"), u64("0x5BDFB684A369DFDF"), u64("0xE57ED79BFCA97E7E"), u64("0x90243DB448192424"),
    u64("0xEC3BC5D776FE3B3B"), u64("0x96AB313D4B9AABAB"), u64("0x1FCE3ED181F0CECE"), u64("0x4411885522991111"),
    u64("0x068F0C8903838F8F"), u64("0x254E4A6B9C044E4E"), u64("0xE6B7D1517366B7B7"), u64("0x8BEB0B60CBE0EBEB"),
    u64("0xF03CFDCC78C13C3C"), u64("0x3E817CBF1FFD8181"), u64("0x6A94D4FE35409494"), u64("0xFBF7EB0CF31CF7F7"),
    u64("0xDEB9A1676F18B9B9"), u64("0x4C13985F268B1313"), u64("0xB02C7D9C58512C2C"), u64("0x6BD3D6B8BB05D3D3"),
    u64("0xBBE76B5CD38CE7E7"), u64("0xA56E57CBDC396E6E"), u64("0x37C46EF395AAC4C4"), u64("0x0C03180F061B0303"),
    u64("0x45568A13ACDC5656"), u64("0x0D441A49885E4444"), u64("0xE17FDF9EFEA07F7F"), u64("0x9EA921374F88A9A9"),
    u64("0xA82A4D8254672A2A"), u64("0xD6BBB16D6B0ABBBB"), u64("0x23C146E29F87C1C1"), u64("0x5153A202A6F15353"),
    u64("0x57DCAE8BA572DCDC"), u64("0x2C0B582716530B0B"), u64("0x4E9D9CD327019D9D"), u64("0xAD6C47C1D82B6C6C"),
    u64("0xC43195F562A43131"), u64("0xCD7487B9E8F37474"), u64("0xFFF6E309F115F6F6"), u64("0x05460A438C4C4646"),
    u64("0x8AAC092645A5ACAC"), u64("0x1E893C970FB58989"), u64("0x5014A04428B41414"), u64("0xA3E15B42DFBAE1E1"),
    u64("0x5816B04E2CA61616"), u64("0xE83ACDD274F73A3A"), u64("0xB9696FD0D2066969"), u64("0x2409482D12410909"),
    u64("0xDD70A7ADE0D77070"), u64("0xE2B6D954716FB6B6"), u64("0x67D0CEB7BD1ED0D0"), u64("0x93ED3B7EC7D6EDED"),
    u64("0x17CC2EDB85E2CCCC"), u64("0x15422A5784684242"), u64("0x5A98B4C22D2C9898"), u64("0xAAA4490E55EDA4A4"),
    u64("0xA0285D8850752828"), u64("0x6D5CDA31B8865C5C"), u64("0xC7F8933FED6BF8F8"), u64("0x228644A411C28686")
}

local C7 = {
    u64("0x186018C07830D818"), u64("0x238C2305AF462623"), u64("0xC63FC67EF991B8C6"), u64("0xE887E8136FCDFBE8"),
    u64("0x8726874CA113CB87"), u64("0xB8DAB8A9626D11B8"), u64("0x0104010805020901"), u64("0x4F214F426E9E0D4F"),
    u64("0x36D836ADEE6C9B36"), u64("0xA6A2A6590451FFA6"), u64("0xD26FD2DEBDB90CD2"), u64("0xF5F3F5FB06F70EF5"),
    u64("0x79F979EF80F29679"), u64("0x6FA16F5FCEDE306F"), u64("0x917E91FCEF3F6D91"), u64("0x525552AA07A4F852"),
    u64("0x609D6027FDC04760"), u64("0xBCCABC89766535BC"), u64("0x9B569BACCD2B379B"), u64("0x8E028E048C018A8E"),
    u64("0xA3B6A371155BD2A3"), u64("0x0C300C603C186C0C"), u64("0x7BF17BFF8AF6847B"), u64("0x35D435B5E16A8035"),
    u64("0x1D741DE8693AF51D"), u64("0xE0A7E05347DDB3E0"), u64("0xD77BD7F6ACB321D7"), u64("0xC22FC25EED999CC2"),
    u64("0x2EB82E6D965C432E"), u64("0x4B314B627A96294B"), u64("0xFEDFFEA321E15DFE"), u64("0x5741578216AED557"),
    u64("0x155415A8412ABD15"), u64("0x77C1779FB6EEE877"), u64("0x37DC37A5EB6E9237"), u64("0xE5B3E57B56D79EE5"),
    u64("0x9F469F8CD923139F"), u64("0xF0E7F0D317FD23F0"), u64("0x4A354A6A7F94204A"), u64("0xDA4FDA9E95A944DA"),
    u64("0x587D58FA25B0A258"), u64("0xC903C906CA8FCFC9"), u64("0x29A429558D527C29"), u64("0x0A280A5022145A0A"),
    u64("0xB1FEB1E14F7F50B1"), u64("0xA0BAA0691A5DC9A0"), u64("0x6BB16B7FDAD6146B"), u64("0x852E855CAB17D985"),
    u64("0xBDCEBD8173673CBD"), u64("0x5D695DD234BA8F5D"), u64("0x1040108050209010"), u64("0xF4F7F4F303F507F4"),
    u64("0xCB0BCB16C08BDDCB"), u64("0x3EF83EEDC67CD33E"), u64("0x05140528110A2D05"), u64("0x6781671FE6CE7867"),
    u64("0xE4B7E47353D597E4"), u64("0x279C2725BB4E0227"), u64("0x4119413258827341"), u64("0x8B168B2C9D0BA78B"),
    u64("0xA7A6A7510153F6A7"), u64("0x7DE97DCF94FAB27D"), u64("0x956E95DCFB374995"), u64("0xD847D88E9FAD56D8"),
    u64("0xFBCBFB8B30EB70FB"), u64("0xEE9FEE2371C1CDEE"), u64("0x7CED7CC791F8BB7C"), u64("0x66856617E3CC7166"),
    u64("0xDD53DDA68EA77BDD"), u64("0x175C17B84B2EAF17"), u64("0x47014702468E4547"), u64("0x9E429E84DC211A9E"),
    u64("0xCA0FCA1EC589D4CA"), u64("0x2DB42D75995A582D"), u64("0xBFC6BF9179632EBF"), u64("0x071C07381B0E3F07"),
    u64("0xAD8EAD012347ACAD"), u64("0x5A755AEA2FB4B05A"), u64("0x8336836CB51BEF83"), u64("0x33CC3385FF66B633"),
    u64("0x6391633FF2C65C63"), u64("0x020802100A041202"), u64("0xAA92AA39384993AA"), u64("0x71D971AFA8E2DE71"),
    u64("0xC807C80ECF8DC6C8"), u64("0x196419C87D32D119"), u64("0x4939497270923B49"), u64("0xD943D9869AAF5FD9"),
    u64("0xF2EFF2C31DF931F2"), u64("0xE3ABE34B48DBA8E3"), u64("0x5B715BE22AB6B95B"), u64("0x881A8834920DBC88"),
    u64("0x9A529AA4C8293E9A"), u64("0x2698262DBE4C0B26"), u64("0x32C8328DFA64BF32"), u64("0xB0FAB0E94A7D59B0"),
    u64("0xE983E91B6ACFF2E9"), u64("0x0F3C0F78331E770F"), u64("0xD573D5E6A6B733D5"), u64("0x803A8074BA1DF480"),
    u64("0xBEC2BE997C6127BE"), u64("0xCD13CD26DE87EBCD"), u64("0x34D034BDE4688934"), u64("0x483D487A75903248"),
    u64("0xFFDBFFAB24E354FF"), u64("0x7AF57AF78FF48D7A"), u64("0x907A90F4EA3D6490"), u64("0x5F615FC23EBE9D5F"),
    u64("0x2080201DA0403D20"), u64("0x68BD6867D5D00F68"), u64("0x1A681AD07234CA1A"), u64("0xAE82AE192C41B7AE"),
    u64("0xB4EAB4C95E757DB4"), u64("0x544D549A19A8CE54"), u64("0x937693ECE53B7F93"), u64("0x2288220DAA442F22"),
    u64("0x648D6407E9C86364"), u64("0xF1E3F1DB12FF2AF1"), u64("0x73D173BFA2E6CC73"), u64("0x124812905A248212"),
    u64("0x401D403A5D807A40"), u64("0x0820084028104808"), u64("0xC32BC356E89B95C3"), u64("0xEC97EC337BC5DFEC"),
    u64("0xDB4BDB9690AB4DDB"), u64("0xA1BEA1611F5FC0A1"), u64("0x8D0E8D1C8307918D"), u64("0x3DF43DF5C97AC83D"),
    u64("0x976697CCF1335B97"), u64("0x0000000000000000"), u64("0xCF1BCF36D483F9CF"), u64("0x2BAC2B4587566E2B"),
    u64("0x76C57697B3ECE176"), u64("0x82328264B019E682"), u64("0xD67FD6FEA9B128D6"), u64("0x1B6C1BD87736C31B"),
    u64("0xB5EEB5C15B7774B5"), u64("0xAF86AF112943BEAF"), u64("0x6AB56A77DFD41D6A"), u64("0x505D50BA0DA0EA50"),
    u64("0x450945124C8A5745"), u64("0xF3EBF3CB18FB38F3"), u64("0x30C0309DF060AD30"), u64("0xEF9BEF2B74C3C4EF"),
    u64("0x3FFC3FE5C37EDA3F"), u64("0x554955921CAAC755"), u64("0xA2B2A2791059DBA2"), u64("0xEA8FEA0365C9E9EA"),
    u64("0x6589650FECCA6A65"), u64("0xBAD2BAB9686903BA"), u64("0x2FBC2F65935E4A2F"), u64("0xC027C04EE79D8EC0"),
    u64("0xDE5FDEBE81A160DE"), u64("0x1C701CE06C38FC1C"), u64("0xFDD3FDBB2EE746FD"), u64("0x4D294D52649A1F4D"),
    u64("0x927292E4E0397692"), u64("0x75C9758FBCEAFA75"), u64("0x061806301E0C3606"), u64("0x8A128A249809AE8A"),
    u64("0xB2F2B2F940794BB2"), u64("0xE6BFE66359D185E6"), u64("0x0E380E70361C7E0E"), u64("0x1F7C1FF8633EE71F"),
    u64("0x62956237F7C45562"), u64("0xD477D4EEA3B53AD4"), u64("0xA89AA829324D81A8"), u64("0x966296C4F4315296"),
    u64("0xF9C3F99B3AEF62F9"), u64("0xC533C566F697A3C5"), u64("0x25942535B14A1025"), u64("0x597959F220B2AB59"),
    u64("0x842A8454AE15D084"), u64("0x72D572B7A7E4C572"), u64("0x39E439D5DD72EC39"), u64("0x4C2D4C5A6198164C"),
    u64("0x5E655ECA3BBC945E"), u64("0x78FD78E785F09F78"), u64("0x38E038DDD870E538"), u64("0x8C0A8C148605988C"),
    u64("0xD163D1C6B2BF17D1"), u64("0xA5AEA5410B57E4A5"), u64("0xE2AFE2434DD9A1E2"), u64("0x6199612FF8C24E61"),
    u64("0xB3F6B3F1457B42B3"), u64("0x21842115A5423421"), u64("0x9C4A9C94D625089C"), u64("0x1E781EF0663CEE1E"),
    u64("0x4311432252866143"), u64("0xC73BC776FC93B1C7"), u64("0xFCD7FCB32BE54FFC"), u64("0x0410042014082404"),
    u64("0x515951B208A2E351"), u64("0x995E99BCC72F2599"), u64("0x6DA96D4FC4DA226D"), u64("0x0D340D68391A650D"),
    u64("0xFACFFA8335E979FA"), u64("0xDF5BDFB684A369DF"), u64("0x7EE57ED79BFCA97E"), u64("0x2490243DB4481924"),
    u64("0x3BEC3BC5D776FE3B"), u64("0xAB96AB313D4B9AAB"), u64("0xCE1FCE3ED181F0CE"), u64("0x1144118855229911"),
    u64("0x8F068F0C8903838F"), u64("0x4E254E4A6B9C044E"), u64("0xB7E6B7D1517366B7"), u64("0xEB8BEB0B60CBE0EB"),
    u64("0x3CF03CFDCC78C13C"), u64("0x813E817CBF1FFD81"), u64("0x946A94D4FE354094"), u64("0xF7FBF7EB0CF31CF7"),
    u64("0xB9DEB9A1676F18B9"), u64("0x134C13985F268B13"), u64("0x2CB02C7D9C58512C"), u64("0xD36BD3D6B8BB05D3"),
    u64("0xE7BBE76B5CD38CE7"), u64("0x6EA56E57CBDC396E"), u64("0xC437C46EF395AAC4"), u64("0x030C03180F061B03"),
    u64("0x5645568A13ACDC56"), u64("0x440D441A49885E44"), u64("0x7FE17FDF9EFEA07F"), u64("0xA99EA921374F88A9"),
    u64("0x2AA82A4D8254672A"), u64("0xBBD6BBB16D6B0ABB"), u64("0xC123C146E29F87C1"), u64("0x535153A202A6F153"),
    u64("0xDC57DCAE8BA572DC"), u64("0x0B2C0B582716530B"), u64("0x9D4E9D9CD327019D"), u64("0x6CAD6C47C1D82B6C"),
    u64("0x31C43195F562A431"), u64("0x74CD7487B9E8F374"), u64("0xF6FFF6E309F115F6"), u64("0x4605460A438C4C46"),
    u64("0xAC8AAC092645A5AC"), u64("0x891E893C970FB589"), u64("0x145014A04428B414"), u64("0xE1A3E15B42DFBAE1"),
    u64("0x165816B04E2CA616"), u64("0x3AE83ACDD274F73A"), u64("0x69B9696FD0D20669"), u64("0x092409482D124109"),
    u64("0x70DD70A7ADE0D770"), u64("0xB6E2B6D954716FB6"), u64("0xD067D0CEB7BD1ED0"), u64("0xED93ED3B7EC7D6ED"),
    u64("0xCC17CC2EDB85E2CC"), u64("0x4215422A57846842"), u64("0x985A98B4C22D2C98"), u64("0xA4AAA4490E55EDA4"),
    u64("0x28A0285D88507528"), u64("0x5C6D5CDA31B8865C"), u64("0xF8C7F8933FED6BF8"), u64("0x86228644A411C286")
}

local rc = {
    u64("0x0000000000000000"),
    u64("0x1823C6E887B8014F"),
    u64("0x36A6D2F5796F9152"),
    u64("0x60BC9B8EA30C7B35"),
    u64("0x1DE0D7C22E4BFE57"),
    u64("0x157737E59FF04ADA"),
    u64("0x58C9290AB1A06B85"),
    u64("0xBD5D10F4CB3E0567"),
    u64("0xE427418BA77D95D8"),
    u64("0xFBEE7C66DD17479E"),
    u64("0xCA2DBF07AD5A8333")
}

local function load_block(cs)
    local block = {}
    local j
    local k

    for i=1,M.block_size,8 do
        j = i//8+1
        k = ((i//8)*8)+1
        block[j] =
            (u64(string.byte(cs._data, k)) << 56 ~
            u64(string.byte(cs._data, k+1)) << 48 ~
            u64(string.byte(cs._data, k+2)) << 40 ~
            u64(string.byte(cs._data, k+3)) << 32 ~
            u64(string.byte(cs._data, k+4)) << 24 ~
            u64(string.byte(cs._data, k+5)) << 16 ~
            u64(string.byte(cs._data, k+6)) << 8 ~
            u64(string.byte(cs._data, k+7)))
    end
    cs._data = cs._data:sub(M.block_size+1)

    return block
end

function M:new(data)
    if self ~= M then
        return nil, "First argument must be self"
    end
    local o = setmetatable({}, M_mt)

    o._hash = {}
    for i=1,8 do
        o._hash[i] = u64(0)
    end
    o._len = u256(0)
    o._data = ""

    if data ~= nil then
        o:update(data)
    end

    return o
end
setmetatable(M, { __call = M.new })

function M:copy()
    local o = M:new()
    for i=1,8 do
        o._hash[i] = self._hash[i]:copy()
    end
    o._data = self._data
    o._len = self._len:copy()
    return o
end

function M:update(data)
    local K = {}
    local state = {}
    local block = {}
    local L = {}

    if data == nil then
        data = ""
    end

    data = tostring(data)
    self._len = self._len + #data * 8
    self._data = self._data .. data

    while #self._data >= M.block_size do
        block = load_block(self)

        K[1] = self._hash[1]:copy()
        K[2] = self._hash[2]:copy()
        K[3] = self._hash[3]:copy()
        K[4] = self._hash[4]:copy()
        K[5] = self._hash[5]:copy()
        K[6] = self._hash[6]:copy()
        K[7] = self._hash[7]:copy()
        K[8] = self._hash[8]:copy()

        state[1] = block[1] ~ K[1]
        state[2] = block[2] ~ K[2]
        state[3] = block[3] ~ K[3]
        state[4] = block[4] ~ K[4]
        state[5] = block[5] ~ K[5]
        state[6] = block[6] ~ K[6]
        state[7] = block[7] ~ K[7]
        state[8] = block[8] ~ K[8]

        for r=2,11 do
            L[1] = 
                C0[((K[1] >> 56)+1):asnumber()] ~
                C1[(((K[8] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[7] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[6] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[5] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[4] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[3] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[2] & 0xFF)+1):asnumber()] ~
                rc[r]
            L[2] = 
                C0[((K[2] >> 56)+1):asnumber()] ~
                C1[(((K[1] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[8] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[7] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[6] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[5] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[4] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[3] & 0xFF)+1):asnumber()]
            L[3] =
                C0[((K[3] >> 56)+1):asnumber()] ~
                C1[(((K[2] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[1] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[8] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[7] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[6] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[5] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[4] & 0xFF)+1):asnumber()]
            L[4] =
                C0[((K[4] >> 56)+1):asnumber()] ~
                C1[(((K[3] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[2] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[1] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[8] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[7] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[6] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[5] & 0xFF)+1):asnumber()]
            L[5] =
                C0[((K[5] >> 56)+1):asnumber()] ~
                C1[(((K[4] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[3] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[2] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[1] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[8] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[7] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[6] & 0xFF)+1):asnumber()]
            L[6] =
                C0[((K[6] >> 56)+1):asnumber()] ~
                C1[(((K[5] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[4] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[3] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[2] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[1] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[8] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[7] & 0xFF)+1):asnumber()]
            L[7] =
                C0[((K[7] >> 56)+1):asnumber()] ~
                C1[(((K[6] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[5] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[4] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[3] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[2] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[1] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[8] & 0xFF)+1):asnumber()]
            L[8] =
                C0[((K[8] >> 56)+1):asnumber()] ~
                C1[(((K[7] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((K[6] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((K[5] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((K[4] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((K[3] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((K[2] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((K[1] & 0xFF)+1):asnumber()]

            K[1] = L[1]:copy()
            K[2] = L[2]:copy()
            K[3] = L[3]:copy()
            K[4] = L[4]:copy()
            K[5] = L[5]:copy()
            K[6] = L[6]:copy()
            K[7] = L[7]:copy()
            K[8] = L[8]:copy()

            L[1] =
                C0[((state[1] >> 56)+1):asnumber()] ~
                C1[(((state[8] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[7] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[6] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[5] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[4] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[3] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[2] & 0xFF)+1):asnumber()] ~
                K[1]
            L[2] =
                C0[((state[2] >> 56)+1):asnumber()] ~
                C1[(((state[1] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[8] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[7] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[6] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[5] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[4] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[3] & 0xFF)+1):asnumber()] ~
                K[2]
            L[3] =
                C0[((state[3] >> 56)+1):asnumber()] ~
                C1[(((state[2] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[1] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[8] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[7] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[6] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[5] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[4] & 0xFF)+1):asnumber()] ~
                K[3]
            L[4] =
                C0[((state[4] >> 56)+1):asnumber()] ~
                C1[(((state[3] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[2] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[1] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[8] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[7] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[6] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[5] & 0xFF)+1):asnumber()] ~
                K[4]
            L[5] =
                C0[((state[5] >> 56)+1):asnumber()] ~
                C1[(((state[4] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[3] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[2] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[1] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[8] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[7] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[6] & 0xFF)+1):asnumber()] ~
                K[5]
            L[6] =
                C0[((state[6] >> 56)+1):asnumber()] ~
                C1[(((state[5] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[4] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[3] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[2] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[1] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[8] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[7] & 0xFF)+1):asnumber()] ~
                K[6]
            L[7] =
                C0[((state[7] >> 56)+1):asnumber()] ~
                C1[(((state[6] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[5] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[4] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[3] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[2] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[1] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[8] & 0xff)+1):asnumber()] ~
                K[7]
            L[8] =
                C0[((state[8] >> 56)+1):asnumber()] ~
                C1[(((state[7] >> 48) & 0xFF)+1):asnumber()] ~
                C2[(((state[6] >> 40) & 0xFF)+1):asnumber()] ~
                C3[(((state[5] >> 32) & 0xFF)+1):asnumber()] ~
                C4[(((state[4] >> 24) & 0xFF)+1):asnumber()] ~
                C5[(((state[3] >> 16) & 0xFF)+1):asnumber()] ~
                C6[(((state[2] >> 8) & 0xFF)+1):asnumber()] ~
                C7[((state[1] & 0xFF)+1):asnumber()] ~
                K[8]

            state[1] = L[1]:copy()
            state[2] = L[2]:copy()
            state[3] = L[3]:copy()
            state[4] = L[4]:copy()
            state[5] = L[5]:copy()
            state[6] = L[6]:copy()
            state[7] = L[7]:copy()
            state[8] = L[8]:copy()
        end

        self._hash[1] = self._hash[1] ~ state[1] ~ block[1]
        self._hash[2] = self._hash[2] ~ state[2] ~ block[2]
        self._hash[3] = self._hash[3] ~ state[3] ~ block[3]
        self._hash[4] = self._hash[4] ~ state[4] ~ block[4]
        self._hash[5] = self._hash[5] ~ state[5] ~ block[5]
        self._hash[6] = self._hash[6] ~ state[6] ~ block[6]
        self._hash[7] = self._hash[7] ~ state[7] ~ block[7]
        self._hash[8] = self._hash[8] ~ state[8] ~ block[8]
    end
end

function M:digest()
    local final
    local out = {}
    local padlen = 0
    local j

    final = self:copy()

    final._data = final._data .. string.char(1<<7)
    if #final._data > 32 then
        final._data = final._data .. string.rep(string.char(0), 64-#final._data)
        padlen = 64-#final._data + 32;
    else
        padlen = 32 - #final._data
    end

    final._data = final._data ..
        string.rep(string.char(0), padlen) ..
        final._len:asbytestring()

    final:update()

    for i=1,#final._hash do
        out[i] = final._hash[i]:asbytestring()
    end

    return table.concat(out)
end

function M:hexdigest()
    local h
    local out = {}

    h = self:digest()
    for i=1,#h do
        out[i] = string.format("%02X", string.byte(h, i))
    end
    return table.concat(out)
end

return M
